package com.lemon.exam.common.util;

import com.lemon.exam.common.exception.CustomException;
import org.springframework.data.relational.core.query.Criteria;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;

import java.util.Map;
import java.util.Objects;

import static com.lemon.exam.common.enums.CodeEnum.ERROR_402;

/**
 * Criteria 条件工具类
 *
 * @author Lemon
 * @since 2025/3/15 19:24
 */
public class CriteriaUtil {
    @SuppressWarnings("all")
    public static Mono<Criteria> toCriteria(Map<String, Object> map) {
        return Mono.fromCallable(() -> {
            //1.判空
            Criteria criteria = Criteria.empty();
            if (CollectionUtils.isEmpty(map)) {
                return criteria;
            }
            //2.获取属性名和列名的映射关系
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                String field = entry.getKey();
                Object value = entry.getValue();

                //3.跳过不存在的属性（是否要映射实体类属性）
                if (!StringUtils.hasText(field) || Objects.isNull(value)) {
                    continue;
                }

                //4.处理属性
                if (value instanceof Map) {
                    for (Map.Entry<String, Object> opEntry : ((Map<String, Object>) value).entrySet()) {
                        criteria = criteria.and(buildCriteria(field, opEntry.getKey(), opEntry.getValue()));
                    }
                } else {
                    criteria = criteria.and(Criteria.where(field).is(value));
                }
            }
            return criteria;
        }).subscribeOn(Schedulers.parallel());
    }

    private static Criteria buildCriteria(String field, String operator, Object value) {
        return switch (operator) {
            case "eq" -> Criteria.where(field).is(value);
            case "not" -> Criteria.where(field).not(value);
            case "gt" -> Criteria.where(field).greaterThan(value);
            case "lt" -> Criteria.where(field).lessThan(value);
            case "like" -> Criteria.where(field).like("%" + value + "%");
            case "ll" -> Criteria.where(field).like("%" + value);
            case "rl" -> Criteria.where(field).like(value + "%");
            case "in" -> Criteria.where(field).in(value);
            default -> throw new CustomException(ERROR_402);
        };
    }
}
